package com.itheima.leetcode.od.b.recursion_single;

import java.util.*;
import java.util.regex.*;

/**
 * (C卷,200分)- 模拟数据序列化传输（Java & JS & Python & C & C++）
 * <p>
 * 题目描述
 * <p>
 * 模拟一套简化的序列化传输方式，请实现下面的数据编码与解码过程
 * <p>
 * 编码前数据格式为 [位置,类型,值]，多个数据的时候用逗号分隔，位置仅支持数字，不考虑重复等场景；类型仅支持：Integer / String / Compose（Compose的数据类型表示该存储的数据也需要编码）
 * <p>
 * 编码后数据参考图示，数据区的格式是：位置#类型#长度#数据，类型存储需要编码，Integer->0；String->1；Compose->2，长度是指数据的字符长度；数据仅允许数字、大小写字母、空格。
 * <p>
 * <p>
 * <p>
 * 输入的编码字符长度不能超过1000，一个数据的格式错误，则解析剩下数据，其他错误输出ENCODE_ERROR。
 * <p>
 * 输入的解码字符不能超过1000，数据区异常则跳过继续解析剩余数据区，其他异常输出DECODE_ERROR。
 * <p>
 * 输入描述
 * <p>
 * 输入有两行：
 * <p>
 * 第一行是命令，1表示编码，2表示解码
 * <p>
 * 第二行输入待编码、解码的字符
 * <p>
 * 数据最多嵌套10层，[1,Compose,[1,String,Second]] 为2层嵌套。
 * <p>
 * 输出描述
 * <p>
 * 如果输入要求是编码，则输出编码结果；
 * <p>
 * 如果输入要求是解码，则输出解码结果；
 * <p>
 * 当异常时输出对应的错误字符。
 * <p>
 * 用例
 * <p>
 * 输入	1
 * <p>
 * [1,String,I am Mary],[2,Integer,23],[3,Long,1000000],[4,Compose,[1,String,I am Kitty],[2,Integer,44]]
 * <p>
 * 输出	1#1#9#I am Mary2#0#2#234#2#25#1#1#10#I am Kitty2#0#2#44
 * <p>
 * 说明	由于Long型为不支持类型，所以数据[3,Long,1000000]自动被过滤掉
 * <p>
 * 输入	2
 * <p>
 * 1#1#9#I am Mary2#0#2#233#0#3#8794#2#25#1#1#10#I am Kitty2#0#2#44
 * <p>
 * 输出	[I,String,I am Mary],[2,Integer,23],[3,Integer,879],[4,Compose,[1,String,I am Kitty],[2,Integer,44]]
 * <p>
 * 说明	无
 * <p>
 * 输入	2
 * <p>
 * xxx
 * <p>
 * 输出	DECODE_ERROR
 * <p>
 * 说明	输入的待解码数据不满足格式要求
 * <p>
 * 输入	1
 * <p>
 * [1,String,I am Mary],[2,Integer,23]],
 * <p>
 * 输出	ENCODE_ERROR
 * <p>
 * 说明	输入格式不满足输入格式要求
 */
public class SimulateDataSerializationTransmission {
    public static void main(String[] args) {
        /*Scanner scanner = new Scanner(System.in);
        String mode = scanner.nextLine().trim();
        String data = scanner.nextLine().trim();
        scanner.close();*/

//        String mode = "1";
//        String data = "[1,String,I am Mary],[2,Integer,23],[3,Long,1000000],[4,Compose,[1,String,I am Kitty],[2,Integer,44]]";

        String mode = "2";
        String data = "1#1#9#I am Mary2#0#2#233#0#3#8794#2#25#1#1#10#I am Kitty2#0#2#44";

        if (data.length() > 1000) {
            System.out.println(mode.equals("1") ? "ENCODE_ERROR" : "DECODE_ERROR");
        } else {
            System.out.println(mode.equals("1") ? encode(data) : decode(data));
        }
    }

    // 定义类型映射
    static Map<String, Integer> TYPE_MAP = new HashMap<>();

    static Map<Integer, String> REVERSE_TYPE_MAP = new HashMap<>();

    static {
        TYPE_MAP.put("Integer", 0);
        TYPE_MAP.put("String", 1);
        TYPE_MAP.put("Compose", 2);
        REVERSE_TYPE_MAP.put(0, "Integer");
        REVERSE_TYPE_MAP.put(1, "String");
        REVERSE_TYPE_MAP.put(2, "Compose");
    }

    /**
     * 编码函数，将输入的嵌套列表数据编码成指定格式
     */
    public static String encode(String data) {
        try {
            List<String> items = parseItems(data);
            List<String> results = new ArrayList<>();

            for (String item : items) {
                String encoded = parseAndEncode(item);
                if (encoded != null) {
                    results.add(encoded);
                }
            }

            return results.isEmpty() ? "ENCODE_ERROR" : String.join("", results);
        } catch (Exception e) {
            return "ENCODE_ERROR";
        }
    }

    /**
     * 解析输入数据中的多个数据项
     */
    private static List<String> parseItems(String data) {
        List<String> items = new ArrayList<>();
        int stack = 0;
        int start = 0;

        for (int i = 0; i < data.length(); i++) {
            char c = data.charAt(i);
            if (c == '[') {
                stack++; // 类似括号匹配
            } else if (c == ']') {
                stack--; // 类似括号匹配
            } else if (c == ',' && stack == 0) {
                items.add(data.substring(start, i).trim());
                start = i + 1;
            }
        }
        items.add(data.substring(start).trim()); // 收尾操作，添加最后一个
        return items;
    }

    /**
     * 解析单个数据项并进行编码
     */
    private static String parseAndEncode(String item) {
        if (!item.startsWith("[") || !item.endsWith("]")) {
            return null;
        }
        item = item.substring(1, item.length() - 1);
        String[] parts = item.split(",", 3); // 规定分割后数组长度
        if (parts.length < 3) {
            return null;
        }

        int pos = Integer.parseInt(parts[0].trim());
        String dtype = parts[1].trim();
        String value = parts[2].trim();

        if (!TYPE_MAP.containsKey(dtype)) {
            return null;
        }

        int dtypeCode = TYPE_MAP.get(dtype);
        if (dtype.equals("Compose")) {
            String nested = encode(value);
            if (nested.equals("ENCODE_ERROR")) {
                return null;
            }
            return pos + "#2#" + nested.length() + "#" + nested;
        } else {
            return pos + "#" + dtypeCode + "#" + value.length() + "#" + value;
        }
    }

    /**
     * 解码函数，将编码后的数据转换回原始格式
     */
    public static String decode(String data) {
        try {
            Pattern pattern = Pattern.compile("(\\d+)#(\\d+)#(\\d+)#");
            Matcher matcher = pattern.matcher(data);
            List<String> results = new ArrayList<>();

            int i = 0;
            while (matcher.find(i)) {
                int pos = Integer.parseInt(matcher.group(1));
                int dtype = Integer.parseInt(matcher.group(2));
                int size = Integer.parseInt(matcher.group(3));

                i = matcher.end();
                if (!REVERSE_TYPE_MAP.containsKey(dtype)) {
                    continue;
                }
                if (i + size > data.length()) {
                    continue;
                }

                String value = data.substring(i, i + size);
                i += size;

                if (dtype == 2) {
                    String nested = decode(value);
                    if (!nested.equals("DECODE_ERROR")) {
                        results.add("[" + pos + ",Compose," + nested + "]");
                    }
                } else {
                    results.add("[" + pos + "," + REVERSE_TYPE_MAP.get(dtype) + "," + value + "]");
                }
            }
            return results.isEmpty() ? "DECODE_ERROR" : String.join(",", results);
        } catch (Exception e) {
            return "DECODE_ERROR";
        }
    }
}